<?php

class users {

	public static function usernameExists($u, $email = false){
		$dbCon = db::singleton();
		
		if($email){
			$sql = "SELECT COUNT(*) AS userExists FROM " . SYS_DB_DBNAME . ".user WHERE emailAddress='" . $dbCon->real_escape_string($u) . "';";		
		} else {
			$sql = "SELECT COUNT(*) AS userExists FROM " . SYS_DB_DBNAME . ".user WHERE userName='" . $dbCon->real_escape_string($u) . "';";
		}
		
		$res = $dbCon->oneRow( $sql );
		
		return (BOOL)$res['userExists'];
			
	}
	
	public static function getUser($u, $byUsername = false){
		$dbCon = db::singleton();
		
		if($byUsername){
			$sql = "SELECT * FROM " . SYS_DB_DBNAME . ".user WHERE userName='" . $dbCon->real_escape_string($u) . "'";
		} else {
			$sql = "SELECT * FROM " . SYS_DB_DBNAME . ".user WHERE emailAddress='" . $dbCon->real_escape_string($u) . "'";
		}
		
		return $dbCon->oneRow($sql);
	}
	
	public static function usernameListExists(array $users){
		/*
		SELECT COUNT(*) AS userExists, emailAddress
		FROM picboard.user 
		WHERE emailAddress='test' OR emailAddress='test'
		GROUP BY emailAddress		
		*/
		
		//Intersections are valid addresses.
		
		$dbCon = db::singleton();
		
		$sql = "SELECT COUNT(*) AS userExists, emailAddress, uID FROM " . SYS_DB_DBNAME . ".user WHERE %s GROUP BY emailAddress";
		
		$out = "";
		
		foreach($users as $user){
			$out .= "emailAddress='" . $dbCon->real_escape_string($user) . "' OR ";
		}
		
		$finishedSQL = sprintf($sql, trim($out, " OR "));
		
		return $dbCon->single( $finishedSQL );
	}
	
	
	
	public static function createUser($data){
		
		$dbCon = db::singleton();
		
		// Does the username exist?		
		if( users::usernameExists($data['userName']) ){
			// This user already exists. abort.
			return Array("status" => "failure", "reason" => "userExists");
		} else {
			if( users::usernameExists($data['email'], true) ) return Array("status" => "failure", "reason" => "emailExists");
			
			// Everything seems okay. Recheck values are not null.
			$ready = true;
			foreach($data as $userDetails){
				if($userDetails == "") $ready = false;
			}
			
			if($ready){
				// Insert the details.
				
				$sql = "INSERT INTO " . SYS_DB_DBNAME . ".user (userName, emailAddress, password, firstName, lastName, isGlobalAdmin, active) VALUES('" . $dbCon->real_escape_string($data['userName']) . "', '" . $dbCon->real_escape_string($data['email']) . "', '" . md5($data['password']) . "', '" . $dbCon->real_escape_string($data['firstname']) . "', '" . $dbCon->real_escape_string($data['surname']) . "', 0, 0)";
				
				$dbCon->single( $sql );
				
				
				// Send the activation email
				$invite = new invite(new template('email.activate'));
				$message = $invite->generateActivationMessage($data['email'], 'userActivation');
				mailHandler::sendMessage($data['email'], "PicBoard Account Activation", $message);
				
				// Write the activation information to the invitations table
				$dbCon->single( "INSERT INTO " . SYS_DB_DBNAME . ".invitations (type, email, actHash, state) VALUES('activation', '" . $dbCon->real_escape_string($data['email']) . "', '" . $invite->getHash() . "', 1)" );
				
				return Array("status" => "success");
			}
		}
		
	}
	
	public static function getUserList(user &$userObj, $filters, $page = 0){
		
		if($userObj->getAccessLevel() != 1) throw new PicBoardException('You do not have permission to perform this action');
		if(is_int($page) == false) throw new PicBoardException("Page number is not an integer.");
		
		$dbCon = db::singleton();
		// Get a list of users		
		
		$template = "SELECT uID, emailAddress, firstName, lastName, isGlobalAdmin, active FROM " . SYS_DB_DBNAME . ".user %s";
		
		
		if($filters['email'] != ""){
			$template = sprintf($template, "WHERE emailAddress LIKE '%%" . $dbCon->real_escape_string($filters['email']) . "%%' %s");
		}
		
		$selector = ($filters['email'] != "") ? "AND" : "WHERE";
		
		//SYS_PAGE_MAXITEMS is the number of items to display per page
		
		$min = $page * SYS_PAGE_MAXITEMS;
		$max = SYS_PAGE_MAXITEMS;
		
		$limitClause = "LIMIT " . $dbCon->real_escape_string($min) . ", " . $dbCon->real_escape_string($max);
			
		switch($filters['state']){
		
			case "allUsers";
				$sql = sprintf($template, "LIMIT " . $dbCon->real_escape_string($min) . ", " . $dbCon->real_escape_string($max));
			break;
			
			
			case "activeUsers":
				$sql = sprintf($template, $selector . " active=1 LIMIT " . $dbCon->real_escape_string($min) . ", " . $dbCon->real_escape_string($max));
			break;
			
			case "activatingUsers":
				$sql = sprintf($template, $selector . " active=0 LIMIT " . $dbCon->real_escape_string($min) . ", " . $dbCon->real_escape_string($max));
			break;
			
			
			case "adminUsers":
				$sql = sprintf($template, $selector . " isGlobalAdmin=1 LIMIT " . $dbCon->real_escape_string($min) . ", " . $dbCon->real_escape_string($max));
			break;
		
			default:
				throw new PicBoardException("Unknown userstate. Unable to fetch.");
			break;
		}

		$resultset = $dbCon->single( $sql );
		$numRows = $dbCon->oneRow( "SELECT FOUND_ROWS()" );
				
		return array("number" => $numRows['FOUND_ROWS()'], "list" => $resultset, "pages" => ceil($numRows['FOUND_ROWS()'] / SYS_PAGE_MAXITEMS) );
		
	}

	public static function removeUsers(user &$userObj, array $userIDs){
		$dbCon = db::singleton();
		
		if($userObj->getAccessLevel() != 1) return array('status' => 'false', 'reason' => 'Insufficient Permissions');
				
		// We are not allowing the root user to be removed for security purposes.
		if(in_array(1, array_values($userIDs))) return array('status' => 'false', 'reason' => 'You are not allowed to remove the root admin.');
		
		if(count($userIDs) > 0){
		
			$sqlTemplate = "DELETE FROM " . SYS_DB_DBNAME . ".user WHERE uID=%d";
			$sqlAdditional = " OR uID=%d";
			
			$result = "";
			
			foreach($userIDs as $k => $user){
				if($k == 0) {
					$result .= sprintf($sqlTemplate, $dbCon->real_escape_string((int)$user));
				} else {
					$result .= sprintf($sqlAdditional, $dbCon->real_escape_string((int)$user));
				}
			}
			
			$dbCon->single( $result );
			return array('status' => 'success');
			
		}
	}
	
	public static function promoteToAdmin( user &$userObj, array $userIDs ){
		if($userObj->getAccessLevel() != 1) return array('status' => false, 'reason' => 'Insufficient Permissions');
		
		$dbCon = db::singleton();
		
		if(count($userIDs) > 0){
			$sqlTemplate = "UPDATE " . SYS_DB_DBNAME . ".user SET isGlobalAdmin=1 WHERE %s";
			
			$output = "";
			
			foreach($userIDs as $user){
				$output .= "uID=" . $dbCon->real_escape_string($user) . " OR ";
			}
			
			$sql = sprintf($sqlTemplate, rtrim($output, " OR "));

			$dbCon->startTransaction();
			
			try {
				$dbCon->single( $sql );
				$dbCon->commit();
				return array('status' => true, 'reason' => 'Success');
			} catch (Exception $e){
				$dbCon->rollback();
				return array('status' => false, 'reason' => 'Unable to promote users');
			}
		}
	}
	
	public static function demoteToUser( user &$userObj, array $userIDs ){
		if($userObj->getAccessLevel() != 1) return array('status' => false, 'reason' => 'Insufficient Permissions');
		
		if(in_array(1, array_values($userIDs))) return array('status' => 'false', 'reason' => 'You are not allowed to remove the root admin.');
		
		$dbCon = db::singleton();
		
		if(count($userIDs) > 0){
			$sqlTemplate = "UPDATE " . SYS_DB_DBNAME . ".user SET isGlobalAdmin=0 WHERE %s";
			
			$output = "";
			
			foreach($userIDs as $user){
				$output .= "uID=" . $dbCon->real_escape_string($user) . " OR ";
			}
			
			$sql = sprintf($sqlTemplate, rtrim($output, " OR "));

			$dbCon->startTransaction();
			
			try {
				$dbCon->single( $sql );
				$dbCon->commit();
				return array('status' => true, 'reason' => 'Success');
			} catch (Exception $e){
				$dbCon->rollback();
				return array('status' => false, 'reason' => 'Unable to demote users');
			}			
		}
		
	}
	
	public static function activateUsers( user &$userObj, array $userIDs ){
		if($userObj->getAccessLevel() != 1) return array('status' => false, 'reason' => 'Insufficient Permissions');
		
		if(in_array(1, array_values($userIDs))) return array('status' => 'false', 'reason' => 'You are not allowed to alter the root admin.');
		
		$dbCon = db::singleton();
		
		if(count($userIDs) > 0){
			$sqlTemplate = "UPDATE " . SYS_DB_DBNAME . ".user SET active=1 WHERE %s";
			
			$output = "";
			
			foreach($userIDs as $user){
				$output .= "uID=" . $dbCon->real_escape_string($user) . " OR ";
			}
			
			$sql = sprintf($sqlTemplate, rtrim($output, " OR "));

			$dbCon->startTransaction();
			
			try {
				$dbCon->single( $sql );
				$dbCon->commit();
				return array('status' => true, 'reason' => 'Success');
			} catch (Exception $e){
				$dbCon->rollback();
				return array('status' => false, 'reason' => 'Unable to activate users');
			}			
		}	
	}
	
	public static function deactivateUsers( user &$userObj, array $userIDs ){
		if($userObj->getAccessLevel() != 1) return array('status' => false, 'reason' => 'Insufficient Permissions');
		
		if(in_array(1, array_values($userIDs))) return array('status' => 'false', 'reason' => 'You are not allowed to alter the root admin.');
		
		$dbCon = db::singleton();
		
		if(count($userIDs) > 0){
			$sqlTemplate = "UPDATE " . SYS_DB_DBNAME . ".user SET active=0 WHERE %s";
			
			$output = "";
			
			foreach($userIDs as $user){
				$output .= "uID=" . $dbCon->real_escape_string($user) . " OR ";
			}
			
			$sql = sprintf($sqlTemplate, rtrim($output, " OR "));

			$dbCon->startTransaction();
			
			try {
				$dbCon->single( $sql );
				$dbCon->commit();
				return array('status' => true, 'reason' => 'Success');
			} catch (Exception $e){
				$dbCon->rollback();
				return array('status' => false, 'reason' => 'Unable to deactivate users');
			}			
		}	
	}

	public static function shareMediaWithUserList( user &$userObj, $chartID, array $userEmails ){
		if($userObj->getAccessLevel() < 0) return array("status" => false, "reason" => "Insufficient Permissions");
		
		$dbCon = db::singleton();
		
		$dbCon->startTransaction();
		
		try {
			$emailSelectTemplate = "SELECT uID, emailAddress FROM " . SYS_DB_DBNAME . ".user WHERE %s";
			$individualTemplate = "emailAddress = \"%s\" OR ";
			// Get the user ID's based on the email addresses.
			$output = "";
			
			foreach($userEmails as $user){
				$output .= sprintf($individualTemplate, $user);
			}
			
			$output = sprintf($emailSelectTemplate, rtrim($output, " OR "));
			
			$emailResult = $dbCon->single( $output );
			
			// Generate the query to create into the table
			
			$insertTemplate = "INSERT INTO " . SYS_DB_DBNAME . ".user_share_chart (uID_from, chart_chID, uID_to) VALUES %s";
			$individualTemplate = "(%d, %d, %d),";
			
			$output = "";
			foreach($emailResult as $user){
				$output .= sprintf($individualTemplate, $userObj->getuID(), (int)$chartID, (int)$user['uID']);
			}
			
			$output = sprintf($insertTemplate, rtrim($output, ","));
			
			$dbCon->single( $output );
			$dbCon->commit();
			return array('status' => true, 'reason' => 'Success');
		} catch (Exception $e){
			$dbCon->rollback();
			return array('status' => false, 'reason' => 'Unable to share content', 'exception'=>$e->getMessage());
		}				
			
	}
	
	public static function removeShare( user &$userObj, $otherUserID, $chartID, $in = true ){
		if($userObj->getAccessLevel() < 0) return array("status" => false, "reason" => "Insufficient Permissions");
		
		$dbCon = db::singleton();
		
		$dbCon->startTransaction();
		
		try {
			if($in){
				$sql = "DELETE FROM " . SYS_DB_DBNAME . ".user_share_chart WHERE chart_chID=" . $dbCon->real_escape_string((int)$chartID) . " AND uID_to=" . $dbCon->real_escape_string($userObj->getuID()) . " AND uID_from=" . $dbCon->real_escape_string($otherUserID);
			} else {
				$sql = "DELETE FROM " . SYS_DB_DBNAME . ".user_share_chart WHERE chart_chID=" . $dbCon->real_escape_string((int)$chartID) . " AND uID_from=" . $dbCon->real_escape_string($userObj->getuID()) . " AND uID_to=" . $dbCon->real_escape_string($otherUserID);
			}
			
			$dbCon->single($sql);
			
			$dbCon->commit();
			return array("status" => true, "reason" => "success");
		} catch (Exception $e){
			$dbCon->rollback();
			return array("status" => false, "reason" => "DBException");
		}
	}

}

?>